package com.lonely.goods.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.goods.domain.dto.goods.GoodsMaterialItemDTO;
import com.lonely.goods.domain.dto.goods.GoodsQuotationSheetPartDTO;
import com.lonely.goods.domain.dto.goods.GoodsQuotationSheetPartMaterialDTO;
import com.lonely.goods.domain.dto.goods.GoodsQuotationSheetSubmitDTO;
import com.lonely.goods.domain.entity.SysGoods;
import com.lonely.goods.domain.entity.SysGoodsPart;
import com.lonely.goods.domain.entity.SysGoodsPartMaterial;
import com.lonely.goods.mapper.SysGoodsPartMaterialMapper;
import com.lonely.goods.service.IGoodsPartMaterialService;
import com.lonely.goods.service.IGoodsPartService;
import com.lonely.goods.service.IGoodsService;
import com.lonely.common.utils.JsonUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : 黄志标
 * @date: 2025/7/2 13:54
 * @description: 商品部件物料服务实现类
 */
@Service
public class GoodsPartMaterialServiceImpl extends ServiceImpl<SysGoodsPartMaterialMapper, SysGoodsPartMaterial> implements IGoodsPartMaterialService {

    @Autowired
    private IGoodsService goodsService;

    @Autowired
    private IGoodsPartService goodsPartService;

    /**
     * 编辑商品报价单部件物料信息
     *
     * @param submitDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitGoodsQuotationSheetPartsMaterial(GoodsQuotationSheetSubmitDTO submitDTO) {

        // 商品部件集合
        List<GoodsQuotationSheetPartDTO> parts = Optional.ofNullable(submitDTO.getParts()).orElse(new ArrayList<>());

        if (CollUtil.isEmpty(submitDTO.getParts())) {
            return;
        }

        // 填充物料明细数据中的当前商品部件的颜色
        submitDTO.setParts(submitDTO.getParts().stream().peek(currentPart -> {
            if (CollUtil.isNotEmpty(currentPart.getPartMaterials())) {
                currentPart.setPartMaterials(currentPart.getPartMaterials().stream().peek(currentPartColorMaterial -> {
                    if (CollUtil.isNotEmpty(currentPartColorMaterial.getMaterials())) {
                        currentPartColorMaterial.setMaterials(currentPartColorMaterial.getMaterials().stream().peek(currentPartColorMaterialMaterial -> {
                            currentPartColorMaterialMaterial.setGoodsColor(currentPartColorMaterial.getGoodsColor());
                        }).collect(Collectors.toList()));
                    }
                }).collect(Collectors.toList()));
            }
        }).collect(Collectors.toList()));

        // 获取当前商品的物料关联id集合
        List<SysGoodsPartMaterial> existsGoodsMaterials = super.list(new LambdaQueryWrapper<SysGoodsPartMaterial>()
                .eq(SysGoodsPartMaterial::getGoodsId, submitDTO.getId())
        );
        List<Long> currentGoodsMaterialIds = existsGoodsMaterials.stream().map(SysGoodsPartMaterial::getId).distinct().collect(Collectors.toList());

        // 当前提交的商品物料集合
        List<GoodsMaterialItemDTO> submitGoodsMaterials = parts.stream().flatMap(x -> Optional.ofNullable(x.getPartMaterials()).orElse(new ArrayList<>()).stream())
                .collect(Collectors.toList())
                .stream().flatMap(x -> Optional.ofNullable(x.getMaterials()).orElse(new ArrayList<>()).stream())
                .collect(Collectors.toList());
        List<Long> submitGoodsMaterialIds = submitGoodsMaterials.stream().map(GoodsMaterialItemDTO::getGoodsPartMaterialId).filter(Objects::nonNull).distinct().collect(Collectors.toList());

        // 对比找出哪些是新增，删除，待修改的数据

        // 待新增的数据
        List<GoodsMaterialItemDTO> needAddGoodsMaterials = submitGoodsMaterials.stream().filter(x -> x.getGoodsPartMaterialId() == null).collect(Collectors.toList());

        // 待删除的数据
        List<Long> needRemoveGoodsMaterialIds = currentGoodsMaterialIds.stream().filter(x -> !submitGoodsMaterialIds.contains(x)).distinct().collect(Collectors.toList());

        // 待更新的数据
        List<Long> needUpdateGoodsMaterialIds = currentGoodsMaterialIds.stream().filter(submitGoodsMaterialIds::contains).distinct().collect(Collectors.toList());


        // 入库
        if (CollUtil.isNotEmpty(needAddGoodsMaterials)) {
            List<SysGoodsPartMaterial> needGoodsPartMaterialModels = needAddGoodsMaterials.stream().map(x -> {
                SysGoodsPartMaterial sysGoodsPartMaterial = new SysGoodsPartMaterial();
                BeanUtils.copyProperties(x, sysGoodsPartMaterial);
                sysGoodsPartMaterial.setGoodsId(submitDTO.getId());
                sysGoodsPartMaterial.setMaterialTypeName(x.getTypeName());
                sysGoodsPartMaterial.setMaterialSku(x.getSku());
                sysGoodsPartMaterial.setMaterialColor(x.getColor());
                sysGoodsPartMaterial.setMaterialPic(x.getPic());
                sysGoodsPartMaterial.setSecondProcess(JsonUtil.toJsonString(x.getSecondProcess()));
                sysGoodsPartMaterial.setCreateBy(SecurityUtils.getUserId());
                sysGoodsPartMaterial.setUpdateBy(SecurityUtils.getUserId());
                sysGoodsPartMaterial.setRemark(x.getRemark());
                return sysGoodsPartMaterial;
            }).collect(Collectors.toList());
            super.saveBatch(needGoodsPartMaterialModels);
        }

        if (CollUtil.isNotEmpty(needRemoveGoodsMaterialIds)) {
            super.removeByIds(needRemoveGoodsMaterialIds);
        }

        if (CollUtil.isNotEmpty(needUpdateGoodsMaterialIds)) {
            Map<Long, GoodsMaterialItemDTO> submitGoodsMaterialMap = submitGoodsMaterials.stream().filter(x -> needUpdateGoodsMaterialIds.contains(x.getGoodsPartMaterialId())).collect(Collectors.toMap(GoodsMaterialItemDTO::getGoodsPartMaterialId, Function.identity(), (a, b) -> b));
            List<SysGoodsPartMaterial> needUpdateGoodsMaterialModels = existsGoodsMaterials.stream().filter(x -> needUpdateGoodsMaterialIds.contains(x.getId()))
                    .peek(x -> {
                        GoodsMaterialItemDTO submitGoodsMaterial = submitGoodsMaterialMap.get(x.getId());
                        BeanUtils.copyProperties(submitGoodsMaterial, x);
                    }).collect(Collectors.toList());
            super.updateBatchById(needUpdateGoodsMaterialModels);

        }

    }

    /**
     * 获取部件id对应的物料信息
     *
     * @param goodsPartId
     * @return
     */
    @Override
    public List<GoodsQuotationSheetPartMaterialDTO> queryPartMaterials(Long goodsPartId) {
        // 查询部件的所有物料信息
        List<SysGoodsPartMaterial> sysGoodsPartMaterials = super.list(new LambdaQueryWrapper<SysGoodsPartMaterial>()
                .eq(SysGoodsPartMaterial::getGoodsPartId, goodsPartId));
        if (CollUtil.isEmpty(sysGoodsPartMaterials)) {
            return new ArrayList<>();
        }

        // 根据颜色和部件分组
        Map<String, List<SysGoodsPartMaterial>> partMaterialGroup = sysGoodsPartMaterials.stream().collect(Collectors.groupingBy(x -> String.format("%s_%s", x.getGoodsPartId(), x.getGoodsColor())));

        List<GoodsQuotationSheetPartMaterialDTO> existsPartMaterials = new ArrayList<>();
        partMaterialGroup.forEach((key, value) -> {
            GoodsQuotationSheetPartMaterialDTO sheetPartMaterialDTO = new GoodsQuotationSheetPartMaterialDTO();
            String[] split = key.split("_");
            sheetPartMaterialDTO.setGoodsPartId(Convert.toLong(split[0]));
            sheetPartMaterialDTO.setGoodsColor(split[1]);

            List<GoodsMaterialItemDTO> goodsMaterialS = value.stream().map(x -> {
                GoodsMaterialItemDTO goodsMaterialItemDTO = new GoodsMaterialItemDTO();
                BeanUtils.copyProperties(x, goodsMaterialItemDTO);
                goodsMaterialItemDTO.setGoodsPartMaterialId(x.getId());
                goodsMaterialItemDTO.setSecondProcess(JsonUtil.parseArray(x.getSecondProcess(), String.class));
                goodsMaterialItemDTO.setSku(x.getMaterialSku());
                goodsMaterialItemDTO.setColor(x.getMaterialColor());
                goodsMaterialItemDTO.setTypeName(x.getMaterialTypeName());
                goodsMaterialItemDTO.setPic(x.getMaterialPic());

                // 计算金额 物料单价 * 单件使用量 * ( 1 + 损耗率/100 ) * ( 1 + 利润率/100 )
                BigDecimal amount = NumberUtil.mul(StrUtil.blankToDefault(x.getUnitPrice(), "0"),
                        StrUtil.blankToDefault(x.getSinglePieceUsage(), "0"),
                        NumberUtil.add(NumberUtil.div(StrUtil.blankToDefault(x.getLoss(), "0"), "100"), new BigDecimal(1)).toPlainString(),
                        NumberUtil.add(NumberUtil.div(StrUtil.blankToDefault(x.getSupplierProfitMargin(), "0"), "100"), new BigDecimal(1)).toPlainString()
                );
                amount = NumberUtil.round(amount, 4);
                goodsMaterialItemDTO.setAmount(amount.toPlainString());
                return goodsMaterialItemDTO;
            }).collect(Collectors.toList());
            sheetPartMaterialDTO.setMaterials(goodsMaterialS);

            existsPartMaterials.add(sheetPartMaterialDTO);
        });

        return existsPartMaterials;
    }

    /**
     * 获取部件id对应的物料信息(全颜色数据，没有配置设置初始值)
     *
     * @param goodsPartId
     * @return
     */
    @Override
    public List<GoodsQuotationSheetPartMaterialDTO> queryQuotationSheetPartMaterials(Long goodsPartId) {
        // 查询已配置的部件物料信息
        List<GoodsQuotationSheetPartMaterialDTO> existsPartMaterials = this.queryPartMaterials(goodsPartId);

        // 根据设置的所有颜色进行适配
        SysGoodsPart goodsPart = this.goodsPartService.getById(goodsPartId);
        Assert.notNull(goodsPart, "部件信息不存在");

        SysGoods sysGoods = this.goodsService.getById(goodsPart.getGoodsId());
        Assert.notNull(sysGoods, "商品信息不存在");

        List<String> colors = JsonUtil.parseArray(sysGoods.getColors(), String.class);
        if (CollUtil.isEmpty(colors)) {
            // 没有设置颜色
            return new ArrayList<>();
        }

        Map<String, GoodsQuotationSheetPartMaterialDTO> colorMaterialMap = existsPartMaterials.stream().collect(Collectors.toMap(GoodsQuotationSheetPartMaterialDTO::getGoodsColor, Function.identity(), (a, b) -> b));
        List<GoodsQuotationSheetPartMaterialDTO> result = new ArrayList<>();
        for (String color : colors) {
            if (colorMaterialMap.containsKey(color)) {
                result.add(colorMaterialMap.get(color));
            } else {
                // 该颜色没有配置，则初始化数据
                GoodsQuotationSheetPartMaterialDTO sheetPartMaterialDTO = new GoodsQuotationSheetPartMaterialDTO();
                sheetPartMaterialDTO.setGoodsPartId(goodsPartId);
                sheetPartMaterialDTO.setGoodsColor(color);
                sheetPartMaterialDTO.setMaterials(new ArrayList<>());
                result.add(sheetPartMaterialDTO);
            }
        }
        return result;
    }
}
